package com.caiyi.financial.nirvana.sms.server;

import com.alibaba.fastjson.JSON;
import com.caiyi.financial.nirvana.sms.enums.SmsMsgStatusEnum;
import com.caiyi.financial.nirvana.sms.gateway.cmpp.CMPPHeader;
import com.caiyi.financial.nirvana.sms.gateway.cmpp.CharsetInfo;
import com.caiyi.financial.nirvana.sms.gateway.cmpp.cmpp20.message.CMPPMessage;
import com.caiyi.financial.nirvana.sms.gateway.cmpp.cmpp20.message.body.CMPPDeliver;
import com.caiyi.financial.nirvana.sms.jedis.JedisKey;
import com.caiyi.financial.nirvana.sms.jedis.JedisService;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class AccountHolder extends Thread {

    private static final Logger logger = LoggerFactory.getLogger(AccountHolder.class);
    private boolean alive = true;
    private String account;
    private ChannelHandlerContext ctx;
    private AtomicInteger deliverCount = new AtomicInteger();

    public AccountHolder(String account, ChannelHandlerContext ctx) {
        this.account = account;
        this.ctx = ctx;
    }

    @Override
    public void run() {
        logger.info("AccountHolder {} start !", account);
        while (alive) {
            try {
                String key = String.format(JedisKey.SMS_QUEUE_CMPP_REPORT_LIST_ACCOUNT, account);
                List<String> list = JedisService.brpop(5, key);
                if (list == null || list.isEmpty()) {
                    continue;
                }
                String value = list.get(1);
                logger.info("AccountHolder run . key : {}, value : {}", list.get(0), value);
                Map notify = JSON.parseObject(value, Map.class);
                sendCmppReport(ctx, notify);
            } catch (Exception e) {
                try {
                    Thread.sleep(1000);
                } catch (Exception e1) {
                }
                logger.error("AccountHolder error !!! ", e);
            }
        }
        logger.info("AccountHolder {} stop !", account);
    }

    private void sendCmppReport(ChannelHandlerContext ctx, Map notify) throws Exception {
        Long messageId = Long.valueOf(notify.get("batchId").toString());
        String phone = notify.get("phone").toString();
        Integer status = (Integer) notify.get("status");
        CMPPMessage message = new CMPPMessage();
        CMPPHeader header = new CMPPHeader();
        header.setCommandID(CMPPMessage.CMPP_DELIVER);
        int seqNo = CMPPServerControlHandler.seqNo.incrementAndGet();
        header.setSequenceId(seqNo);
        message.setHeader(header);

        CMPPDeliver delivery = new CMPPDeliver();
        delivery.setMessageId(messageId);
        delivery.setDestId(phone);
        delivery.setMessageFormat(CharsetInfo.UCS2);
        delivery.setSrcTerminalId(phone);
        delivery.setIsDelivery((byte) 1);
        delivery.setReportMessageId(messageId);
        if (status == SmsMsgStatusEnum.SEND_SUCCESS.index) {
            delivery.setStat("DELIVRD");
        } else {
            delivery.setStat("UNDELIV");
        }
        String receiveTime = notify.get("receiveTime").toString();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = simpleDateFormat.parse(receiveTime).getTime() / 1000 + "";
        delivery.setSubmitTime(time);
        delivery.setDoneTime(time);
        delivery.setDestTerminalId(phone);
        message.setBody(delivery);
        ctx.writeAndFlush(message).addListener((future) -> logger.info("sendCmppReport phone : {}, messageId : {}, isDone : {}, isSuccess : {}", phone, messageId, future.isDone(), future.isSuccess())).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public void shutdown() {
        alive = false;
        this.interrupt();
    }

    public AtomicInteger getDeliverCount() {
        return deliverCount;
    }
}
